home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
devices
/
msh_1_5
/
part02
< prev
next >
Wrap
Internet Message Format
|
1990-02-21
|
47KB
Path: xanth!cs.odu.edu!Amiga-Request
From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
Newsgroups: comp.sources.amiga
Subject: v90i080: MSH 1.5 - Messydos File System Handler , Part02/06
Message-ID: <11499@xanth.cs.odu.edu>
Date: 21 Feb 90 01:58:35 GMT
Sender: tadguy@cs.odu.edu
Reply-To: Olaf 'Rhialto' Seibert <U211344%HNYKUN11.BITNET@CUNYVM.CUNY.EDU>
Lines: 1497
Approved: tadguy@cs.odu.edu (Tad Guy)
X-Mail-Submissions-To: Amiga@cs.odu.edu
X-Post-Discussions-To: comp.sys.amiga
Submitted-by: Olaf 'Rhialto' Seibert <U211344%HNYKUN11.BITNET@CUNYVM.CUNY.EDU>
Posting-number: Volume 90, Issue 080
Archive-name: devices/msh-1.5/part02
#!/bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 6)."
# Contents: doc/dev.man.uu src/hanlock.c src/hanmain.c
# Wrapped by tadguy@xanth on Tue Feb 20 20:57:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/dev.man.uu' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/dev.man.uu'\"
else
echo shar: Extracting \"'doc/dev.man.uu'\" \(14325 characters\)
sed "s/^X//" >'doc/dev.man.uu' <<'END_OF_FILE'
Xbegin 664 dev.man
XM"B`@("`@;65S<WED:7-K+F1E=FEC92@I("`@($%M:6=A(%!R;V=R86UM97(GW
XM<R!-86YU86P@("`@(&UE<W-Y9&ES:RYD979I8V4H*0H*"@H@("`@()LQ;5-9)
XM3D]04UE3(`H@("`@("`@("`@FS!M(VEN8VQU9&4@/&5X96,O:6\N:#X*("`@;
XM("`@("`@("-I;F-L=61E(#QD979I8V5S+W1R86-K9&ES:RYH/@H@("`@("`@3
XM("`@(VEN8VQU9&4@/&1E=BYH/@H*("`@("`@("`@($]P96Y$979I8V4H(FUEH
XM<W-Y9&ES:RYD979I8V4B+"!5;FET+"!)3T5X=%1$+"!&;&%G<RD["B`@("`@J
XM("`@("!"96=I;DE/*$E/17AT5$0I.PH@("`@("`@("`@0VQO<V5$979I8V4H"
XM24]%>'141"D["@H@("`@()LQ;55304=%(`H@("`@("`@("`@FS!M365S<WED^
XM:7-K+F1E=FEC92`@8V%N("!B92`@=7-E9"!I;G-T96%D(&]F('1R86-K9&ES!
XM:RYD979I8V4N"B`@("`@("`@("!!;&P@8W5R<F5N="!T<F%C:V1I<VLN9&5V*
XM:6-E(&-O;6UA;F1S(&%R92`@<W5P<&]R=&5D+B`@("!4:&4*("`@("`@("`@:
XM(&]N;'D@(&9U;F-T:6]N86P@9&EF9F5R96YC92!I<R!T:&4@9F]R;6%T(&]F[
XM('1H92!D:7-K+"!W:&EC:`H@("`@("`@("`@:7,@8V]M<&%T:6)L92!W:71H-
XM(&UE<W-Y9&]S('-Y<W1E;7,N("`*"B`@("`@FS%M0T]-34%.1%,@"B`@("`@&
XM("`@("";,&U3=7!P;W)T960@8V]M;6%N9',@87)E.B`*"B`@("`@("`@("`]3
XM($--1%])3E9!3$E$("`@("`]($--1%]215-%5"`@("`@("`J($--1%]214%$&
XM"B`@("`@("`@("`J($--1%]74DE412`@("`@("`J($--1%]54$1!5$4@("`@R
XM("`]($--1%]#3$5!4@H@("`@("`@("`@/2!#341?4U1/4"`@("`@("`@/2!#W
XM341?4U1!4E0@("`@("`@/2!#341?1DQ54T@*("`@("`@("`@("`@5$1?34]4A
XM3U(@("`@("`@(#T@5$1?4T5%2R`@("`@("`@("H@5$1?1D]234%4"B`@("`@Q
XM("`@("`@(%1$7U)%34]612`@("`@("`@(%1$7T-(04Y'14Y532`@("`@(%1$J
XM7T-(04Y'15-4051%"B`@("`@("`@("`@(%1$7U!23U135$%455,@("`@(%1$H
XM7U)!5U)%040@("`@("`@(%1$7U)!5U=2251%"B`@("`@("`@("`@(%1$7T=%>
XM5$12259%5%E012`@(%1$7T=%5$Y5351204-+4R`](%1$7T%$1$-(04Y'14E.Y
XM5`H@("`@("`@("`@/2!41%]214U#2$%.1T5)3E0@*B!%5$1?5U))5$4@("`@8
XM("`@*B!%5$1?4D5!1`H@("`@("`@("`@("!%5$1?34]43U(@("`@("`@/2!%;
XM5$1?4T5%2R`@("`@("`@*B!%5$1?1D]234%4"B`@("`@("`@("`J($541%]53
XM4$1!5$4@("`@("`]($541%]#3$5!4B`@("`@("`@($541%]205=214%$"B`@:
XM("`@("`@("`@($541%]205=74DE410H*("`@("`@("`@(%1H92!C;VUM86YDE
XM<R!M87)K960@=VET:"`J(&%R92!H86YD;&5D(&EN(&ET<R!O=VX@9F]R;6%TY
XM("!B>0H@("`@("`@("`@;65S<WED:7-K+B`@(%1H92`@8V]M;6%N9',@(&UA0
XM<FME9"`@=VET:"`@/2`@87)E("!H86YD;&5D(&)Y"B`@("`@("`@("!M97-SD
XM>61I<VL@:6X@=&AE('-A;64@=V%Y(&%S('1R86-K9&ES:R!S=7!P;W-E9"`@:
XM:7,@('1O("!D;RX*("`@("`@("`@(%1H92`@;W1H97(@(&-O;6UA;F1S("!A`
XM<F4@<V5N="!S=')A:6=H="!T:')O=6=H('1O('1R86-K9&ES:PH@("`@("`@E
XM("`@86YD(&%R92!S=6)J96-T('1O(&%L;"!I=',@9FQA=W,@86YD(&9E871U,
XM<F5S+B`@"@H@("`@()LQ;4]014Y$159)0T4@1DQ!1U,@"B`@("`@("`@("";9
XM,&U41$9?04Q,3U=?3D].7S-?-3H@06QL;W=S(&]P96YI;F<@-#`@=')A8VL@^
XM9')I=F5S+B`@26=N;W)E9"P*("`@("`@("`@('-I;F-E(&ET(&ES('1H92!DI
XM969A=6QT(&)E:&%V:6]U<B!W:&EC:"!C86YN;W0@8F4@9&ES86)L960N("`*S
XM"B`@("`@FS%M24\@4D5154535"!&3$%'4R`*("`@("`@("`@()LP;51H92!I=
XM;U]&;&%G<R!F:65L9"!O9B!A;B!)3U-T9%)E<2!O<B!)3T5X=%1$("!S=')U>
XM8W1U<F4@(&UA>0H@("`@("`@("`@8V]N=&%I;B!T:&4@9F]L;&]W:6YG(&9LD
XM86=S.B`*"B`@("`@("`@("!)3T9?455)0TLZ(%1H:7,@9FQA9R!I<R!S=7!PS
XM;W)T960@9F]R(&]N;'D@82!F97<@8V]M;6%N9',N("`*"B`@("`@("`@("!)'
XM3U1$1E])3D1%6%-93D,Z($9O<B!%5$0O0TU$7U)!5U)%040@86YD(%]74DE4_
XM12X@(`H*("`@("`@("`@($E/341&7S0P5%)!0TM3.B`@5&AI<R`@9FQA9R`@M
XM:7,@(&9O<B`@151$+T--1%]214%$+"`@7U=2251%+`H@("`@("`@("`@7T9/^
XM4DU!5"P@86YD(%]3145++B`@268@<V5T+"!T<F5A="!T:&4@9&ES:R!A<R`@O
XM-#`@(&-Y;&EN9&5R"B`@("`@("`@("!M961I82X@("!)9B`@:70@:&%P<&5N^
XM<R!T;R!B92!I;B!A;B`X,"!C>6QI;F1E<B!D<FEV92P@979E<GD*("`@("`@`
XM("`@(&]T:&5R(&-Y;&EN9&5R('=I;&P@8F4@<VMI<'!E9"!T;R!U<V4@=&AE\
XM('-A;64@(&-Y;&EN9&5R<R`@80H@("`@("`@("`@-#`M8WEL:6YD97(@9')I(
XM=F4@('=O=6QD+B`@("!.;W)M86QL>2`@>6]U('-E="!O<B!C;&5A<B!T:&ES+
XM"B`@("`@("`@("!F;&%G(&]N8V4@870@=&AE('1I;64@>6]U(')E860@=&AEH
XM(&)O;W1B;&]C:R!A;F0@97AA;6EN92!I=',*("`@("`@("`@(&QA>6]U="!I:
XM;F9O<FUA=&EO;BX@($ET(&ES(&=U87)A;G1E960@=&AA="`@;65S<WED:7-K1
XM("!W;VXG=`H@("`@("`@("`@8VAA;F=E('1H:7,@(&9L86<N("`@($E/341&N
XM7S0P5%)!0TM3("!I<R`@;F]T("!S=7!P;W)T960@9F]R"B`@("`@("`@("!%4
XM5$0O5$1?4D%74D5!1"!A;F0@7U)!5U=2251%+"!S:6YC92!T:&5S92!A<F4@:
XM8V]N<VED97)E9"`@=&\*"@H@("`@($MO<VUO4V]F="`@("`@("`@("`@("`@F
XM("`@("`@("`@("TQ+2`@("`@("`@("`@("`@("`@("`@("!697)S:6]N(#,TX
XM+C4*"@H@("`@(&UE<W-Y9&ES:RYD979I8V4H*2`@("!!;6EG82!0<F]G<F%M#
XM;65R)W,@36%N=6%L("`@("!M97-S>61I<VLN9&5V:6-E*"D*"@H@("`@("`@%
XM("`@8F4@(")D:6%G;F]S=&EC(B!F=6YC=&EO;G,@86YD('1H97)E9F]R92!S3
XM:&]U;&0@8F4@87,@<F%W(&%S"B`@("`@("`@("!P;W-S:6)L92X@(`H*("`@B
XM("";,6U$25-+($9/4DU!5"`*("`@("`@("`@()LP;51H92!D:7-K(&9O<FUA0
XM="!U<V5D(&ES(&-O;7!A=&EB;&4@('=I=&@@(&UE<W-Y9&]S("!S>7-T96US,
XM+@H@("`@("`@("`@0F]T:"`T,"`@86YD("`X,"`@8WEL:6YD97(@(&UE9&EA^
XM("!A<F4@<W5P<&]R=&5D+B`@5&AE<F4@87)E"B`@("`@("`@("!N;W)M86QL[
XM>2`Y('-E8W1O<G,@<&5R('1R86-K(&%N9"!T=V\@('1R86-K<R`@<&5R("!C0
XM>6QI;F1E<BX*("`@("`@("`@("A/=71D871E9"D@('-I;F=L92US:61E9"`@R
XM9&ES:W,@(&-A;B`@;VYL>2`@8F4@(')E860@(&EF('1H90H@("`@("`@("`@O
XM9')I=FEN9R`@<V]F='=A<F4@(&ES("!P<F5P87)E9"`@=&\@('1R96%T("!T$
XM:&5M("!A<R`@;F]R;6%L"B`@("`@("`@("!D;W5B;&4M<VED960@9&ES:W,L\
XM(&%N9"!S:VEP('1H92!S:61E<R!T:&%T(&%R92!N;W0@86-T=6%L;'D*("`@&
XM("`@("`@('!R97-E;G0N("!/;B!T:&4@;W1H97(@:&%N9"P@=&AE(&YU;6)EN
XM<B!O9B!S96-T;W)S('!E<B!T<F%C:PH@("`@("`@("`@;6%Y('9A<GD@9G)O`
XM;2`X('1O(#$P+B!)9B!T:&4@;G5M8F5R(&]F('-E8W1O<G,@:7,@9&EF9F5RT
XM96YT"B`@("`@("`@("!F<F]M("!T:&4@(&1E9F%U;'0@=F%L=64@*#DI+"!T2
XM:&5N('1R86-K(#`@;VX@<VED92`P(&UU<W0@8F4*("`@("`@("`@(')E860@H
XM9FER<W0@8F5F;W)E('1H:7,@:7,@<F5C;V=N:7IE9"X@($ET("!I<R`@=&AEA
XM;B`@87-S=6UE9`H@("`@("`@("`@=&AA="`@86QL("!T<F%C:W,@;VX@=&AEZ
XM(&5N=&ER92!D:7-K(&AA=F4@=&AE('-A;64@;G5M8F5R(&]F"B`@("`@("`@%
XM("!S96-T;W)S+B`@4V\L(&%L;"!P;W-I=&EO;B!C86QC=6QA=&EO;G,@(&%R"
XM92`@8F%S960@(&]N("!T:&4*("`@("`@("`@(&QA>6]U="!O9B!T:&4@=F5RM
XM>2!F:7)S="!T<F%C:RX@(`H*("`@("`@("`@("TM+2!);F1E>"!P=6QS92`@@
XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+@H@("`@("`@L
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@@
XM("`@("`@("`@("!\"B`@("`@("`@("`@("`@-C`@*B`D-&4@("`@1T%0(#$@\
XM("`H)#DR-30@96YC;V1E9"D@("`@("`@("`@("`@('P*("`@("`@("`@("`@!
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@@
XM("`@("`@?`H@("`@("`@("`@+2TM($9I<G-T(%-E8W1O<B`M+2TM+2TM+2TMG
XM+2TM+2TM+2TM+2TM+2TM+2TM+2X@("`@("!\"B`@("`@("`@("`@("`@("`@K
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@?"`@("`@\
XM('P*("`@("`@("`@("`@("`Q,B`J("0P,"`@("!'05`@,B`@("@D04%!02!E6
XM;F-O9&5D*2`@("`@("!\("`@("`@?`H@("`@("`@("`@('P@("`S("H@)&$Q'
XM("`@(%-93D,@("`@*"0T-#@Y(&5N8V]D960I("`@("`@('P@("`@("!\"B`@?
XM("`@("`@("`@?"`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@\
XM("`@("`@("`@?"`@("`@('P*("`@("`@("`@("!\("`@,2`J("1F92`@("!)Q
XM1"U!9&1R97-S($UA<FL@("`M+B`H)#4U-30I("!\("`@("`@?`H@("`@("`@G
XM("`@('P@('1R86-K("`@("`@("`@("`@("`@("`@("`@("`@("!\("`@("`@-
XM("`@('P@("`@("!\"B`@("`@("`@("`@?"`@<VED92`@("`@("`@("`@("`@#
XM("`@("`@("`@("`@('P@("`@("`@("`@?"`@("`@('P*("`@("`@("`@("!\Z
XM("!S96-T;W(@("`@("`@("`@("`@("`@("`@("`@("`@(#X@240@("`@("!\W
XM("`@("`@?`H@("`@("`@("`@('P@(&QE;F=T:"`H,#TQ,C@L,3TR-38L,CTU[
XM,3(@971C+BE\("!&:65L9"`@('P@(%,@("!\"B`@("`@("`@("`@+3X@0U)#.
XM(#$@("`@("`@("`@("`@("`@("`@("`@("`@('P@("`@("`@("`@?"`@92`@N
XM('P@(%0*("`@("`@("`@("`M/B!#4D,@,B`@("`@("`@("`@("`@("`@("`@/
XM("`@("`M)R`@("`@("`@("!\("!C("`@?"`@<@H@("`@("`@("`@("`@("`@K
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`^('0@2
XM("`@/B!A"B`@("`@("`@("`@("`@,C(@*B`D-&4@("`@1T%0(#$@("`H)#DRT
XM-30@96YC;V1E9"D@("`@("`@?"`@;R`@('P@(&,*("`@("`@("`@("`@("`Q)
XM,B`J("0P,"`@("!'05`@,B`@("@D04%!02!E;F-O9&5D*2`@("`@("!\("!RC
XM("`@?"`@:PH@("`@("`@("`@('P@("`S("H@)&$Q("`@(%-93D,@("`@*"0T=
XM-#@Y(&5N8V]D960I("`@("`@('P@("`@("!\"B`@("`@("`@("`@?"`@("`@>
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@?"`@("`@\
XM('P*("`@("`@("`@("!\("`@,2`J("1F8B`@("!$051!+4%D<F5S<R!-87)K]
XM("`M+B`H)#4U-#4I("!\("`@("`@?`H@("`@("`@("`@('P@(#4Q,B!B>71E-
XM<R!D871A("`@("`@("`@("`@("`@("`@/B!$051!("`@('P@("`@("!\"B`@G
XM("`@("`@("`@+3X@0U)#(#$@("`@("`@("`@("`@("`@("`@("`@("`@('P@P
XM($9I96QD("`@?"`@("`@('P*("`@("`@("`@("`M/B!#4D,@,B`@("`@("`@[
XM("`@("`@("`@("`@("`@("`M)R`@("`@("`@("!\("`@("`@?`H@("`@("`@6
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@@
XM("`@('P@("`@("!\"B`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@"
XM("`@("`@("`@("`@("`@("`@("`@("`@?"`@("`@('P*("`@("`@("`@("`@"
XM("`X,"`J("0T92`@("!'05`@,R`@("@D.3(U-"!E;F-O9&5D*2`@("`@("!\Q
XM("`@("`@?`H@("`@("`@("`@+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM%
XM+2TM+2TM+2TM+2TM+2TM+2TM+2<@("`@("!\"B`@("`@("`@("`@("`@("`@D
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@@
XM('P*("`@("`@("`@("`N+BXN+BX@."!M;W)E('-E8W1O<G,@+BXN+BXN+B`@*
XM("`@("`@("`@("`@("`@("`@("`@?`H@("`@("`@("`@("`@("`@("`@("`@F
XM("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("!\"B`@F
XM("`@("`@("`@("`@<F5S="`@)#1E("`@("`@("`@("`H)#DR-30@96YC;V1E)
XM9"D@("`@("`@("`@("`@('P*("`@("`@("`@("TM+2TM+2TM+2TM+2TM+2TM0
XM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM+2TM)PH*("`@("";*
XM,6U$159)051)3TY3(`H@("`@("`@("`@FS!M5&AE(%1$7U)%34-(04Y'14E./
XM5"!C;VUM86YD('=O<FMS+B`@*$ET(&1O97-N)W0@=VET:"!T:&4@,2XR"B`@(
XM("`@("`@("!O<B`Q+C,@=')A8VMD:7-K+F1E=FEC92DN("`*"@H*"B`@("`@Z
XM2V]S;6]3;V9T("`@("`@("`@("`@("`@("`@("`@("`@+3(M("`@("`@("`@1
XM("`@("`@("`@("`@(%9E<G-I;VX@,S0N-0H*"B`@("`@;65S<WED:7-K+F1E!
XM=FEC92@I("`@($%M:6=A(%!R;V=R86UM97(G<R!-86YU86P@("`@(&UE<W-Y\
XM9&ES:RYD979I8V4H*0H*"B`@("`@("`@("!4:&4@("!M97-S>61I<VL@("!5*
XM;FET("`@<W1R=6-T=7)E("`@9&]E<R`@(&YO="`@(&QO;VL@(&QI:V4*("`@\
XM("`@("`@(%1$55]0=6)L:6-5;FET(&%T(&%L;"X@(`H*("`@("`@("`@($ENR
XM('-O;64@<VET=6%T:6]N<RP@97)R;W(@<F5T=7)N<R!M87D@8F4@9&EF9F5R.
XM96YT("!O<B`@;&5S<PH@("`@("`@("`@<W!E8VEF:6,N("`*"B`@("`@("`@Q
XM("!$871A("!B=69F97)S("!T;R!B92!R96%D(&]R('=R:71T96X@8W5R<F5N*
XM=&QY(&1O;B=T(&YE960@=&\*("`@("`@("`@(&)E(&EN($-H:7`@;65M;W)YY
XM+B`@5&AI<R!M:6=H="!C:&%N9V4@:6X@=&AE("!F=71U<F4N("`@($9O<@H@W
XM("`@("`@("`@9G5T=7)E("!C;VUP871I8FEL:71Y("!A;F0@('=I=&@@('1H`
XM92`@=')A8VMD:7-K+F1E=FEC92`@>6]U"B`@("`@("`@("!S:&]U;&0@;F]TJ
XM(&1E<&5N9"!O;B!T:&ES+B`@"@H@("`@("`@("`@26X@;W)D97(@=&\@8F4@D
XM86)L92!T;R!F;W)M870@82`@=')A8VL@('=I=&@@(&$@(&YO;G-T86YD87)D/
XM"B`@("`@("`@("!N=6UB97(@;V8@<V5C=&]R<R`H9G)O;2`X('1O(#$P*2P@X
XM>6]U(&UU<W0@=7-E('1H92!41%]&3U)-050*("`@("`@("`@(&-O;6UA;F0@]
XM('=I=&@@(&QE<W,@=&AA;B`T,"!S96-T;W)S("@R,#0X,"!B>71E<RD@870@0
XM82!T:6UE+@H@("`@("`@("`@4VEN8V4@>6]U(&UU<W0@86QW87ES(&9O<FUAF
XM="!E;G1I<F4@=')A8VMS(&%T(&$@('1I;64L("!T:&ES"B`@("`@("`@("!U+
XM;FEQ=65L>2`@9&5T97)M:6YE<R`@=&AE(&YU;6)E<B!O9B!S96-T;W)S('EO!
XM=2!W86YT(&]N(&5A8V@*("`@("`@("`@('1R86-K+B`@5&AE(&-U<G)E;G0@N
XM;G5M8F5R(&]F('-E8W1O<G,@<&5R('1R86-K+"!W:&EC:"`@=VEL;`H@("`@>
XM("`@("`@8F4@('5S960@(&QA=&5R("!W:&5N(')E861I;F<@9G)O;2!T:&4@1
XM<V%M92!D:7-K+"!I<R!U<&1A=&5D"B`@("`@("`@("!A8V-O<F1I;F=L>2X@'
XM("!)9B`@>6]U("`@<W!E8VEF>2`@(#0P("`@<V5C=&]R<R`@(&]R("`@;6]RU
XM92P*("`@("`@("`@(&UE<W-Y9&ES:RYD979I8V4@9&]E<R!N;W0@871T96UP\
XM="!T;R!G=65S<R!W:&%T('EO=2!W86YT(&)U=`H@("`@("`@("`@<VEM<&QY\
XM('5S97,@('1H92`@=F%L=64@('1H870@('=A<R!A;')E861Y('-E="X@(%-O8
XM+"!Y;W4@;6%Y"B`@("`@("`@("!C:&]O<V4@=&\@9FER<W0@(&9O<FUA="`@O
XM82`@<VEN9VQE("!T<F%C:R`@=&\@(&EN9&EC871E("!T:&4*("`@("`@("`@'
XM(&1E<VER960@(&YU;6)E<B`@;V8@('-E8W1O<G,@<&5R('1R86-K+"!A;F0@<
XM=&AE;B!I;B!O;F4@8V%L;`H@("`@("`@("`@9F]R;6%T('1H92!E;G1I<F4@_
XM<F5S="!O9B!T:&4@9&ES:RX@(`H*("`@("`@("`@(%=H96X@82!D:7-K('=I_
XM=&@@;6]R92!O<B!L97-S('1H86X@.2!S96-T;W)S("!P97(@('1R86-K("!I3
XM<PH@("`@("`@("`@<F5A9"P@('EO=2!M=7-T(&9I<G-T(&ES<W5E(&$@0TU$1
XM7U)%040@8V]M;6%N9"!F;W(@=&AE(&9I<G-T"B`@("`@("`@("!S96-T;W(H,
XM<RD@;V8@('1H92`@(&1I<VLN("`@("`@5VAE;B`@('1R86-K("`@,"`@(&ES>
XM("`@<F5A9"P*("`@("`@("`@(&UE<W-Y9&ES:RYD979I8V4@(&1E=&5R;6EN$
XM97,@:&]W(&UA;GD@<V5C=&]R<R!T:&5R92!A<F4@;VX@80H@("`@("`@("`@6
XM=')A8VLN("!4:&ES(&YU;6)E<B!I<R!T:&5N('5S960@869T97)W87)D<R!W*
XM:&5N(&-A;&-U;&%T:6YG"B`@("`@("`@("!T:&4@=')A8VMS(&%N9"!S:61EM
XM<R!O9B!O=&AE<B!S96-T;W)S+B`@(%-O+"`@=&AI<R`@:7,@('9E<GD*("`@-
XM("`@("`@(&EM<&]R=&%N="X@($)U="!F;W(@=&AO<V4@*'9I<G1U86QL>2!I^
XM;7!O<W-I8FQE*2!C87-E<R!W:&5R90H@("`@("`@("`@;F]T("!A;&P@=')A<
XM8VMS(&AA=F4@=&AE('-A;64@;G5M8F5R(&]F('-E8W1O<G,L(&%L;"!S96-T!
XM;W)S"B`@("`@("`@("!T:&%T("!W97)E("!R96%D("!O;B`@86YY("!T<F%CM
XM:R`@=VEL;"`@8F4@("!W<FET=&5N("`@8F%C:RX*("`@("`@("`@($9O<G1U0
XM;F%T96QY+"`@(&%L;"`@8W5R<F5N=&QY("!K;F]W;B`@9FEL92`@<WES=&5ML
XM<R`@:&%V92`@80H@("`@("`@("`@8F]O=&)L;V-K("!A="`@=')A8VL@(#`L'
XM("!S:61E("`P+"`@('-O("`@=&AE>2`@(&%L;"`@(&%D87!T"B`@("`@("`@J
XM("!T<F%N<W!A<F5N=&QY+B`@"@H@("`@()LQ;4-!5D5!5%,@"B`@("`@("`@C
XM("";,&U4:&4@*&]U=&1A=&5D*2!41%]214U/5D4@8V]M;6%N9"!I<R!R;W5TN
XM960@=&\@=')A8VMD:7-K+B`@07,*("`@("`@("`@(&$@(')E<W5L="!O9B!TA
XM:&ES+"!O;FQY(&]N92!D:7-K(')E;6]V92!I;G1E<G)U<'0@*'!E<B!U;FETI
XM*0H@("`@("`@("`@;6%Y("!B92`@:6YS=&%L;&5D("`H=VET:"`@=&AI<R`@=
XM8V]M;6%N9"DL("!W:&5T:&5R("!T:')O=6=H"B`@("`@("`@("!T<F%C:V1I8
XM<VL@;W(@(&UE<W-Y9&ES:RX@("`@*%1H:7,@('-E96US("!T;R`@:&%V92`@-
XM8F5E;B!T:&4*("`@("`@("`@(&]R:6=I;F%L("!I;G1E;G1I;VX@(&]F("!4;
XM1%]214U/5D4N*2`@3V8@("!C;W5R<V4L("`@8W5R<F5N=`H@("`@("`@("`@'
XM<')O9W)A;7,@<VAO=6QD('5S92!41%]!1$1#2$%.1T5)3E0N("`*"B`@("`@:
XMFS%M551)3$E42453(`H@("`@("`@("`@FS!M02`@<V5P87)A=&4@('!R;V=R7
XM86T@(&-A;&QE9"`@26=N;W)E("!I<R!S=7!P;&EE9"P@=VAI8V@@;6%Y"B`@)
XM("`@("`@("!S=7!P<F5S<R!T:&4@0U)#(&-H96-K(&EN(&%N>2!C=7)R96YT^
XM;'D@;W!E;B!U;FET+B`@5VAE;B!T:&4*("`@("`@("`@('5N:70@:7,@9&5F-
XM:6YI=&EV96QY(&-L;W-E9"!A;F0@;&%T97(@<F5O<&5N960L(&EG;F]R:6YG=
XM($-20PH@("`@("`@("`@;6ES;6%T8VAE<R!A9V%I;B!H87,@:71S(&1E9F%U!
XM;'0@=F%L=64@;V8@3F\N("`*"B`@("`@("`@("!5<V%G93H@:6=N;W)E(#QU5
XM;FET;G(^(#Q915,O3D\^"@H@("`@("`@("`@268@>6]U(&]N;'D@9VEV92!T!
XM:&4@=6YI="!N=6UB97(L(&EG;F]R92!W:6QL(&]U='!U="`@96ET:&5R"B`@:
XM("`@("`@("!997,@(&]R("!.;RP@<F5F;&5C=&EN9R!W:&5T:&5R($-20R!M:
XM:7-M871C:&5S(&-U<G)E;G1L>2!A<F4*("`@("`@("`@(&EG;F]R960N("`*+
XM"@H*("`@("!+;W-M;U-O9G0@("`@("`@("`@("`@("`@("`@("`@("`M,RT@0
XM("`@("`@("`@("`@("`@("`@("`@5F5R<VEO;B`S-"XU"@H*("`@("!M97-SF
XM>61I<VLN9&5V:6-E*"D@("`@06UI9V$@4')O9W)A;6UE<B=S($UA;G5A;"`@&
XM("`@;65S<WED:7-K+F1E=FEC92@I"@H*("`@("`@("`@(%1H:7,@<')O9W)A,
XM;2!C86X@8F4@=7-E9G5L('=H96X@>6]U("!W:7-H("!T;R`@<F5C;W9E<B`@]
XM9&%T80H@("`@("`@("`@9G)O;2!A("!D86UA9V5D("!O<B!M87)G:6YA;"!DL
XM:7-K+B`@4V]M971I;65S('1E>'0@9FEL97,@;6%Y"B`@("`@("`@("!B92!U0
XM<V%B;&4@979E;B!I9B!T:&5R92!A<F4@82!F97<@97)R;W)S(&EN('1H96TNG
XM("`*"B`@("`@FS%M05542$]24R`*("`@("`@("`@()LP;4UE<W-Y9&ES:R!IZ
XM<R!W<FET=&5N(&)Y()LS;5-O=7)C97)E<B";,&U/;&%F()LS;5)H:6%L=&\@8
XMFS!M4V5I8F5R="X@(%1H90H@("`@("`@("`@;&]W+6QE=F5L("`@=W)I=&ENS
XM9R`@<&%R="`@=V%S("!O<FEG:6YA;&QY("!D;VYE("!B>2`@5V5R;F5R"B`@A
XM("`@("`@("!'_&YT:&5R+B!5<V5D('=I=&@@<&5R;6ES<VEO;BX@(`H*"@H*H
XM"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"
XM"@H*("`@("!+;W-M;U-O9G0@("`@("`@("`@("`@("`@("`@("`@("`M-"T@1
XC("`@("`@("`@("`@("`@("`@("`@5F5R<VEO;B`S-"XU"@H@D
X``
Xend
Xsize 10205
END_OF_FILE
if test 14325 -ne `wc -c <'doc/dev.man.uu'`; then
echo shar: \"'doc/dev.man.uu'\" unpacked with wrong size!
fi
# end of 'doc/dev.man.uu'
fi
if test -f 'src/hanlock.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/hanlock.c'\"
else
echo shar: Extracting \"'src/hanlock.c'\" \(17870 characters\)
sed "s/^X//" >'src/hanlock.c' <<'END_OF_FILE'
X/*-
X * $Id: hanlock.c,v 1.4 90/01/27 20:22:17 Rhialto Exp $
X * $Log: hanlock.c,v $
X * Revision 1.4 90/01/27 20:22:17 Rhialto
X * Added extra check when freeing MSFileLocks.
X *
X * Revision 1.3 90/01/23 00:36:57 Rhialto
X * Add an #ifndef READONLY.
X *
X * Revision 1.2 89/12/17 23:05:33 Rhialto
X * Add MSSetProtect
X *
X * Revision 1.1 89/12/17 20:03:01 Rhialto
X *
X * HANLOCK.C
X *
X * The code for the messydos file system handler
X *
X * The Lock department. Takes care of operations on locks, and consequently,
X * on directories.
X *
X * This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
X * not be used or copied without a licence.
X-*/
X
X#include "han.h"
X#include "dos.h"
X
X#ifdef DEBUG
X# define debug(x) dbprintf x
X#else
X# define debug(x)
X#endif
X
Xstruct LockList *LockList; /* List of all locked files we have. Note
X * this is not the same as all locks we
X * have */
Xstruct MSFileLock *RootLock; /* Lock on root directory */
Xstruct MSFileLock *EmptyFileLock; /* 2nd result of MSLock() */
X
Xstruct DirEntry FakeRootDirEntry = {
X { /* de_Msd */
X "Unnamed ", /* msd_Name */
X " ", /* msd_Ext */
X ATTR_VOLUMELABEL, /* msd_Attributes */
X {0}, /* msd_Pad1 */
X 0, /* msd_Time */
X 0x21, /* msd_Date, 1/1/80 */
X 0, /* msd_Cluster */
X 0 /* msd_Filesize */
X },
X -1, /* de_Sector */
X 0 /* de_Offset */
X};
Xbyte DotDot[1 + 8 + 3] = ".. ";
X
X/*
X * This routine compares a name in a directory entry with a given name
X */
X
Xint
XCompareNames(dir, name)
Xregister struct MsDirEntry *dir;
Xregister byte *name;
X{
X#ifdef DEBUG
X if (name[0] == '\\') {
X extern short DBEnable;
X
X DBEnable = name[1] & 0x0F;
X
X return CMP_END_OF_DIR;
X }
X#endif
X
X if (dir->msd_Name[0] & DIR_DELETED_MASK)
X return CMP_FREE_SLOT;
X
X if (dir->msd_Name[0] == 0)
X return CMP_END_OF_DIR; /* end of directory */
X
X if (dir->msd_Attributes & ATTR_VOLUMELABEL)
X return CMP_NOT_EQUAL;
X
X if (strncmp(dir->msd_Name, name, 8 + 3))
X return CMP_NOT_EQUAL;
X
X if (dir->msd_Attributes & ATTR_DIRECTORY)
X return CMP_OK_DIR;
X
X return CMP_OK_FILE;
X}
X
Xvoid
XNextDirEntry(sector, offset)
Xregister word *sector;
Xregister word *offset;
X{
X if ((*offset += MS_DIRENTSIZE) >= Disk.bps) {
X *offset = 0;
X if (*sector >= Disk.datablock) {
X /* Must be subdirectory */
X *sector = NextClusteredSector(*sector);
X debug(("NextClusteredSector: %d\n", *sector));
X } else {
X if (++*sector >= Disk.datablock) {
X *sector = SEC_EOF;
X }
X }
X }
X /* else no more work needed */
X}
X
X/*
X * Get the directory entry following the given one. If requested, we make
X * the directory longer.
X */
X
Xstruct DirEntry *
XFindNext(previous, createit)
Xregister struct DirEntry *previous;
Xint createit;
X{
X byte *sector;
X word prevsec = previous->de_Sector;
X
X NextDirEntry(&previous->de_Sector, &previous->de_Offset);
X
X if (previous->de_Sector == SEC_EOF) {
X error = ERROR_OBJECT_NOT_FOUND;
X#ifndef READONLY
X if (createit) {
X if (prevsec < Disk.datablock - 1) { /* Should not be necessary */
X previous->de_Sector = prevsec + 1;
X } else if (prevsec >= Disk.datablock) {
X previous->de_Sector = FindFreeSector(prevsec);
X }
X if (previous->de_Sector != SEC_EOF) {
X sector = EmptySec(previous->de_Sector);
X setmem(sector, (int) Disk.bps, 0);
X MarkSecDirty(sector);
X FreeSec(sector);
X setmem(&previous->de_Msd, sizeof (previous->de_Msd), 0);
X
X return previous;
X }
X }
X#endif
X } else if (sector = GetSec(previous->de_Sector)) {
X CopyMem(sector + previous->de_Offset, &previous->de_Msd,
X (long) MS_DIRENTSIZE);
X OtherEndianMsd(&previous->de_Msd);
X FreeSec(sector);
X
X return previous;
X }
X return NULL;
X}
X
X#ifdef DEBUG
X
Xvoid
XPrintDirEntry(de)
Xstruct DirEntry *de;
X{
X debug(("%d,%d ", de->de_Sector, de->de_Offset));
X debug(("%.8s.%.3s attr:%x time:%x date:%x start:%x size:%lx\n",
X de->de_Msd.msd_Name,
X de->de_Msd.msd_Ext,
X de->de_Msd.msd_Attributes,
X de->de_Msd.msd_Time,
X de->de_Msd.msd_Date,
X de->de_Msd.msd_Cluster,
X de->de_Msd.msd_Filesize
X ));
X}
X
X#endif
X
X/*
X * MakeLock makes a struct MSFileLock from a directory entry and the
X * parent directory MSFileLock pointer. It looks if it already has a Lock
X * on it. In that case, it simply increments its reference count, when
X * possible.
X */
X
Xstruct MSFileLock *
XMakeLock(parentdir, dir, mode)
Xstruct MSFileLock *parentdir;
Xstruct DirEntry *dir;
Xulong mode;
X{
X register struct MSFileLock *fl;
X struct MSFileLock *nextfl;
X
X if (mode != EXCLUSIVE_LOCK || (dir->de_Msd.msd_Attributes & ATTR_DIR))
X mode = SHARED_LOCK;
X
X#ifdef DEBUG
X debug(("MakeLock: "));
X PrintDirEntry(dir);
X#endif
X
X /*
X * Look through our list to see if we already have it. The criteria
X * for this are: 1. the directory entries are the same or 2. they have
X * the same first cluster and are both directories (which can have
X * multiple directory entries). Sigh.
X */
X
X for (fl = (struct MSFileLock *) LockList->ll_List.mlh_Head;
X nextfl = (struct MSFileLock *) fl->msfl_Node.mln_Succ;
X fl = nextfl) {
X#ifdef DEBUG
X debug(("> "));
X PrintDirEntry(&fl->msfl_Msd);
X#endif
X if ((fl->msfl_DirSector == dir->de_Sector &&
X fl->msfl_DirOffset == dir->de_Offset) ||
X (fl->msfl_Msd.msd_Cluster == dir->de_Msd.msd_Cluster &&
X (dir->de_Msd.msd_Attributes & ATTR_DIR) &&
X (fl->msfl_Msd.msd_Attributes & ATTR_DIR))
X ) {
X /* Found existing lock on file */
X if (fl->msfl_Refcount < 0 || mode == EXCLUSIVE_LOCK) {
X error = ERROR_OBJECT_IN_USE;
X return NULL;
X }
X fl->msfl_Refcount++;
X return fl;
X }
X }
X
X fl = AllocMem((long) sizeof (*fl), MEMF_PUBLIC);
X if (fl == NULL) {
X error = ERROR_NO_FREE_STORE;
X return NULL;
X }
X fl->msfl_Parent = parentdir ? MSDupLock(parentdir) : NULL;
X
X fl->msfl_Refcount = (mode == EXCLUSIVE_LOCK) ? -1 : 1;
X fl->msfl_DirSector = dir->de_Sector;
X fl->msfl_DirOffset = dir->de_Offset;
X fl->msfl_Msd = dir->de_Msd;
X
X AddHead(&LockList->ll_List, fl);
X
X return fl;
X}
X
X/*
X * This routine Locks a file. It first searches it in the directory, then
X * lets the rest of the work be done by MakeLock(). If it encounters an
X * empty slot in the directory, it remembers where, in case we need it. If
X * you clear the MODE_CREATEFILE bit in the mode parameter, we fabricate a
X * new MSFileLock from the empty directory entry. It then becomes the
X * caller's responsibility to MSUnLock() it eventually.
X */
X
Xstruct MSFileLock *
XMSLock(parentdir, name, mode)
Xstruct MSFileLock *parentdir;
Xbyte *name;
Xulong mode;
X{
X byte *sector;
X struct MSFileLock *newlock;
X register struct DirEntry *de;
X struct DirEntry sde;
X byte *nextpart;
X byte component[8 + 3]; /* Note: not null-terminated */
X int createit;
X word freesec;
X word freeoffset;
X
X de = &sde;
X newlock = NULL;
X
X /*
X * See if we have an absolute path name (starting at the root).
X */
X
X {
X register byte *colon;
X
X if (colon = index(name, ':')) {
X name = colon + 1;
X parentdir = RootLock;
X }
X }
X
X /*
X * Get a copy of the parent dir lock, so we can walk it over the
X * directory tree.
X */
X parentdir = MSDupLock(parentdir);
X
X /*
X * Start with the directory entry of the parent dir.
X */
X
X sde.de_Msd = parentdir->msfl_Msd;
X sde.de_Sector = parentdir->msfl_DirSector;
X sde.de_Offset = parentdir->msfl_DirOffset;
X#ifdef DEBUG
X debug(("pdir %08lx: ", parentdir));
X PrintDirEntry(&parentdir->msfl_Msd);
X#endif
X
Xnewdir:
X freesec = SEC_EOF; /* Means none found yet */
X
X nextpart = ToMSName(component, name);
X debug(("Component: '%11s'\n", component));
X if (nextpart[0] != '/') {
X nextpart = NULL;
X#ifndef READONLY
X /*
X * See if we are requested to get an empty spot in the directory
X * if the given name does not exist already. The value of mode is
X * not important until we actually create the filelock.
X */
X if (!(mode & MODE_CREATEFILE)) {
X mode ^= MODE_CREATEFILE;
X createit = 1;
X } else
X createit = 0;
X#endif
X } else
X nextpart++;
X
X /*
X * Are we at the end of the name? Then we are finished now. This works
X * because sde contains the directory entry of parentdir.
X */
X
X if (name[0] == '\0')
X goto exit;
X
X /*
X * If there is more name, we enter the directory, and here we get the
X * first entry.
X */
X
X sde.de_Sector = DirClusterToSector(sde.de_Msd.msd_Cluster);
X sde.de_Offset = 0;
X
X if ((sector = GetSec(sde.de_Sector)) == NULL)
X goto error;
X
X CopyMem(sector, &sde.de_Msd, (long) sizeof (struct MsDirEntry));
X OtherEndianMsd(&sde.de_Msd);
X FreeSec(sector);
X
X while (de) {
X switch (CompareNames(&sde.de_Msd, component)) {
X case CMP_FREE_SLOT:
X if (freesec == SEC_EOF) {
X freesec = sde.de_Sector;
X freeoffset = sde.de_Offset;
X }
X /* Fall through */
X case CMP_NOT_EQUAL:
X de = FindNext(&sde, createit); /* Try next directory
X * entry */
X continue;
X case CMP_OK_DIR:
X if (name = nextpart) {
X /*
X * We want to keep locks on all directories between each
X * bottom directory and file lock, so we can easily find
X * the parent of a lock. There just seems to be a problem
X * here when we enter the 'subdirectories' . or .. , but
X * that in not so: MakeLock will detect that it has
X * already a lock on those, and NOT make :one/two the
X * parent of :one/two/.. .
X */
X newlock = MakeLock(parentdir, de, SHARED_LOCK);
X MSUnLock(parentdir);
X parentdir = newlock;
X goto newdir;
X }
X goto exit;
X case CMP_OK_FILE:
X if (nextpart) {
X error = ERROR_OBJECT_WRONG_TYPE;
X de = NULL;
X }
X goto exit;
X case CMP_END_OF_DIR: /* means we will never find it */
X error = ERROR_OBJECT_NOT_FOUND;
X if (freesec == SEC_EOF) {
X freesec = sde.de_Sector;
X freeoffset = sde.de_Offset;
X }
X de = NULL;
X goto exit;
X }
X }
X
Xexit:
X if (de) {
X newlock = MakeLock(parentdir, &sde, mode);
X } else {
X newlock = NULL;
X#ifndef READONLY
X if (createit && /* Do we want to make it? */
X error == ERROR_OBJECT_NOT_FOUND && /* does it not exist yet? */
X nextpart == NULL) { /* do we have the last part of the name */
X if (freesec != SEC_EOF) { /* is there any room? */
X if (IDDiskState == ID_VALIDATED) {
X error = 0;
X setmem(&sde.de_Msd, sizeof (sde.de_Msd), 0);
X sde.de_Sector = freesec;
X sde.de_Offset = freeoffset;
X /* ToMSName(sde.de_Msd.msd_Name, name); */
X strncpy(sde.de_Msd.msd_Name, component, 8 + 3);
X EmptyFileLock = MakeLock(parentdir, &sde, mode);
X WriteFileLock(EmptyFileLock);
X } else
X error = ERROR_DISK_WRITE_PROTECTED;
X } else
X error = ERROR_DISK_FULL;
X }
X#endif
X }
X
Xerror:
X MSUnLock(parentdir);
X
X return newlock;
X}
X
X/*
X * This routine DupLocks a file. This simply means incrementing the
X * reference count, if it was not an exclusive Lock.
X */
X
Xstruct MSFileLock *
XMSDupLock(fl)
Xstruct MSFileLock *fl;
X{
X if (fl == NULL)
X fl = RootLock;
X if (fl->msfl_Refcount <= 0) {
X error = ERROR_OBJECT_IN_USE;
X return NULL;
X } else {
X fl->msfl_Refcount++;
X }
X
X return fl;
X}
X
X/*
X * This routine DupLocks the parent of a lock, if there is one.
X */
X
Xstruct MSFileLock *
XMSParentDir(fl)
Xregister struct MSFileLock *fl;
X{
X if (fl == NULL || fl == RootLock) {
X error = ERROR_OBJECT_NOT_FOUND;
X } else if (fl->msfl_Parent)
X return MSDupLock(fl->msfl_Parent);
X
X return NULL;
X}
X
X/*
X * This routine UnLocks a file.
X */
X
Xint
XMSUnLock(fl)
Xstruct MSFileLock *fl;
X{
X#ifdef DEBUG
X debug(("MSUnLock %08lx: ", fl));
X PrintDirEntry(&fl->msfl_Msd);
X#endif
X
X if (fl) {
X if (--fl->msfl_Refcount <= 0) {
X struct LockList *list;
X
X list = (struct LockList *) fl->msfl_Node.mln_Pred;
X Remove(fl);
X debug(("Remove()d %08lx\n", fl));
X
X /*
X * We may need to get rid of the LockList if it is empty. This
X * is the current LockList iff we are called from
X * MSDiskRemoved(). Please note that we are not even sure that
X * 'list' really is the list header, therefore the careful
X * test if fl refers to a volume label (root lock) which is
X * finally UnLock()ed. Because of the recursion, we only try to
X * free the LockList iff there is no parent anymore, since
X * otherwise list may be invalid by the time we use it.
X */
X if (fl->msfl_Parent) {
X MSUnLock(fl->msfl_Parent);
X } else {
X if ((fl->msfl_Msd.msd_Attributes & ATTR_VOLUMELABEL) &&
X ((void *) list->ll_List.mlh_Head ==
X (void *) &list->ll_List.mlh_Tail)
X ) {
X FreeLockList(list);
X }
X }
X FreeMem(fl, (long) sizeof (*fl));
X }
X }
X return DOSTRUE;
X}
X
X/*
X * This is (among other things) the inverse of ToMSName().
X */
X
Xvoid
XExamineDirEntry(msd, fib)
Xstruct MsDirEntry *msd;
Xregister struct FileInfoBlock *fib;
X{
X register byte *end,
X *dot;
X
X#ifdef DEBUG
X debug(("+ "));
X PrintDirEntry(msd);
X#endif
X strncpy(&fib->fib_FileName[1], msd->msd_Name, 8);
X /* Keep at least one character, even a space, before the dot */
X dot = ZapSpaces(&fib->fib_FileName[2], &fib->fib_FileName[1 + 8]);
X dot[0] = ' ';
X strncpy(dot + 1, msd->msd_Ext, 3);
X dot[4] = '\0';
X end = ZapSpaces(dot, dot + 4);
X if (end > dot)
X dot[0] = '.';
X fib->fib_FileName[0] = strlen(&fib->fib_FileName[1]);
X
X fib->fib_DirEntryType =
X (msd->msd_Attributes & ATTR_DIR) ? FILE_DIR : FILE_FILE;
X fib->fib_Protection = 0;
X if (!(msd->msd_Attributes & ATTR_ARCHIVED))
X fib->fib_Protection |= FIBF_ARCHIVE;
X if (msd->msd_Attributes & ATTR_READONLY)
X fib->fib_Protection |= (FIBF_WRITE | FIBF_DELETE);
X if (msd->msd_Attributes & (ATTR_HIDDEN|ATTR_SYSTEM))
X fib->fib_Protection |= FIBF_HIDDEN;
X fib->fib_Size = msd->msd_Filesize;
X fib->fib_NumBlocks = (msd->msd_Filesize + Disk.bps - 1) / Disk.bps;
X ToDateStamp(&fib->fib_Date, msd->msd_Date, msd->msd_Time);
X fib->fib_Comment[0] = 0;
X}
X
Xint
XMSExamine(fl, fib)
Xstruct MSFileLock *fl;
Xregister struct FileInfoBlock *fib;
X{
X if (fl == NULL)
X fl = RootLock;
X
X fib->fib_DiskKey = ((ulong) fl->msfl_DirSector << 16) | fl->msfl_DirOffset;
X fib->fib_EntryType = 0; /* No ExNext called yet */
X ExamineDirEntry(&fl->msfl_Msd, fib);
X
X return DOSTRUE;
X}
X
Xint
XMSExNext(fl, fib)
Xstruct MSFileLock *fl;
Xregister struct FileInfoBlock *fib;
X{
X word sector = fib->fib_DiskKey >> 16;
X word offset = (word) fib->fib_DiskKey;
X byte *buf;
X
X if (fl == NULL)
X fl = RootLock;
X
X if (fib->fib_EntryType == 0) {
X fib->fib_EntryType = 1;
X if (fl->msfl_Msd.msd_Attributes & ATTR_DIR) {
X /* Enter subdirectory */
X sector = DirClusterToSector(fl->msfl_Msd.msd_Cluster);
X offset = 0;
X } else
X NextDirEntry(§or, &offset);
X } else {
Xskip:
X NextDirEntry(§or, &offset);
X }
X
X if (sector != SEC_EOF) {
X register struct MsDirEntry *msd;
X
X if (buf = GetSec(sector)) {
X msd = (struct MsDirEntry *) (buf + offset);
X if (msd->msd_Name[0] == '\0') {
X FreeSec(buf);
X goto end;
X }
X if (msd->msd_Name[0] & DIR_DELETED_MASK ||
X msd->msd_Name[0] == '.' || /* Hide "." and ".." */
X (msd->msd_Attributes & ATTR_VOLUMELABEL)) {
X FreeSec(buf);
X goto skip;
X }
X OtherEndianMsd(msd);/* Get correct endianness */
X fib->fib_DiskKey = ((ulong) sector << 16) | offset;
X ExamineDirEntry(msd, fib);
X OtherEndianMsd(msd);/* Get wrong endianness */
X FreeSec(buf);
X
X return DOSTRUE;
X }
X }
Xend:
X error = ERROR_NO_MORE_ENTRIES;
X return DOSFALSE;
X}
X
X/*
X * Convert AmigaDOS protection bits to messy attribute bits.
X */
X
Xlong
XMSSetProtect(parentdir, name, mask)
Xregister struct MSFileLock *parentdir;
Xchar *name;
Xlong mask;
X{
X register struct MSFileLock *lock;
X
X if (parentdir == NULL)
X parentdir = RootLock;
X
X lock = MSLock(parentdir, name, EXCLUSIVE_LOCK);
X if (lock) {
X /* Leave SYSTEM bit as-is */
X lock->msfl_Msd.msd_Attributes &= ATTR_SYSTEM;
X /* write or delete protected -> READONLY */
X if (mask & (FIBF_WRITE|FIBF_DELETE))
X lock->msfl_Msd.msd_Attributes |= (ATTR_READONLY);
X /* hidden -> hidden */
X if (mask & FIBF_HIDDEN)
X lock->msfl_Msd.msd_Attributes |= (ATTR_HIDDEN);
X /* archived=0 (default) -> archived=1 (default) */
X if (!(mask & FIBF_ARCHIVE))
X lock->msfl_Msd.msd_Attributes |= (ATTR_ARCHIVED);
X WriteFileLock(lock);
X MSUnLock(lock);
X return TRUE;
X }
X
X return FALSE;
X}
X
Xint
XCheckLock(lock)
Xregister struct MSFileLock *lock;
X{
X register struct MSFileLock *parent;
X
X if (lock) {
X while (parent = lock->msfl_Parent)
X lock = parent;
X if (lock != RootLock)
X error = ERROR_DEVICE_NOT_MOUNTED;
X }
X return error;
X}
X
X#ifndef READONLY
X
Xvoid
XWriteFileLock(fl)
Xregister struct MSFileLock *fl;
X{
X debug(("WriteFileLock %08lx\n", fl));
X
X if (fl) {
X register byte *block = GetSec(fl->msfl_DirSector);
X
X if (block) {
X CopyMem(&fl->msfl_Msd, block + fl->msfl_DirOffset,
X (long) sizeof (fl->msfl_Msd));
X OtherEndianMsd(block + fl->msfl_DirOffset);
X MarkSecDirty(block);
X FreeSec(block);
X }
X }
X}
X
Xvoid
XUpdateFileLock(fl)
Xregister struct MSFileLock *fl;
X{
X struct DateStamp dateStamp;
X
X debug(("UpdateFileLock %08lx\n", fl));
X
X DateStamp(&dateStamp);
X ToMSDate(&fl->msfl_Msd.msd_Date, &fl->msfl_Msd.msd_Time, &dateStamp);
X WriteFileLock(fl);
X}
X
X#endif
X
Xstruct LockList *
XNewLockList(cookie)
Xvoid *cookie;
X{
X struct LockList *ll;
X
X if (ll = AllocMem((long) sizeof (*ll), MEMF_PUBLIC)) {
X NewList(&ll->ll_List);
X ll->ll_Cookie = cookie;
X } else
X error = ERROR_NO_FREE_STORE;
X
X return ll;
X}
X
Xvoid
XFreeLockList(ll)
Xstruct LockList *ll;
X{
X debug(("FreeLockList %08lx\n", ll));
X
X if (ll) {
X MayFreeVolNode(ll->ll_Cookie); /* not too happy about this */
X FreeMem(ll, (long) sizeof (*ll));
X if (ll == LockList) /* locks on current volume */
X LockList = NULL;
X }
X}
END_OF_FILE
if test 17870 -ne `wc -c <'src/hanlock.c'`; then
echo shar: \"'src/hanlock.c'\" unpacked with wrong size!
fi
# end of 'src/hanlock.c'
fi
if test -f 'src/hanmain.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/hanmain.c'\"
else
echo shar: Extracting \"'src/hanmain.c'\" \(10114 characters\)
sed "s/^X//" >'src/hanmain.c' <<'END_OF_FILE'
X/*-
X * $Id: hanmain.c,v 1.4 90/01/27 20:13:00 Rhialto Exp $
X * $Log: hanmain.c,v $
X * Revision 1.4 90/01/27 20:13:00 Rhialto
X * *** empty log message ***
X *
X * Revision 1.3 89/12/17 21:29:51 Rhialto
X * *** empty log message ***
X *
X * Revision 1.1 89/12/17 20:02:31 Rhialto
X * Initial revision
X *
X *
X * HANMAIN.C
X *
X * The code for the messydos file system handler.
X *
X * Some start/stop stuff that is not really part of the
X * file system itself but that must be done anyway.
X *
X * This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
X * not be used or copied without a licence.
X-*/
X
X#include "han.h"
X#include "dos.h"
X
X#ifdef DEBUG
X# define debug(x) dbprintf x
X#else
X# define debug(x)
X#endif
X
Xextern char DotDot[1 + 8 + 3];
Xstruct Library *IntuitionBase;
Xstatic char RCSId[] = "Messydos filing system $Revision: 1.4 $ $Date: 90/01/27 20:13:00 $, by Olaf Seibert";
X
Xbyte
XToUpper(ch)
Xregister byte ch;
X{
X if (ch >= 'a' && ch <= 'z')
X return ch + ('A' - 'a');
X if (ch == '.')
X return '!';
X return ch & ~DIR_DELETED_MASK;
X}
X
Xlong
Xlmin(a, b)
Xlong a,
X b;
X{
X return (a < b) ? a : b;
X}
X
Xbyte *
XZapSpaces(begin, end)
Xregister byte *begin,
X *end;
X{
X while (end > begin && end[-1] == ' ')
X *--end = '\0';
X
X return end;
X}
X
X/*
X * Map an arbitrary file name to MS-DOS conventions. The output format is
X * 8+3 without dot, padded with spaces, suitable for direct comparison
X * with directory entries. Return a pointer to the delimiter found ('\0'
X * or '/'). [[Make sure that Examine/ExNext return a proper inverse of
X * this...]]
X */
X
Xbyte *
XToMSName(dest, source)
Xbyte *dest;
Xregister byte *source;
X{
X byte *dotp;
X byte *slashp;
X register int i,
X len;
X
X if (*source == '/') { /* parentdir */
X strncpy(dest, DotDot, 8 + 3); /* ".." */
X return source;
X }
X /*
X * Remove any strictly leading dots. .info -> info, .indent.pro ->
X * indent.pro, .profile -> profile, etc.
X */
X while (*source == '.')
X source++;
X
X /*
X * Find dot and slash which are delimiters of name and extension.
X */
X {
X register byte *cp;
X
X cp = source;
X while (*cp) {
X if (*cp == '.' || *cp == '/')
X break;
X cp++;
X }
X dotp = cp;
X while (*cp) {
X if (*cp == '/')
X break;
X cp++;
X }
X slashp = cp;
X }
X
X len = dotp - source;
X if (len > 8)
X len = 8;
X
X for (i = 0; i < len; i++) {
X *dest++ = ToUpper(*source++);
X }
X for (; i < 8; i++) {
X *dest++ = ' ';
X }
X
X source = dotp + 1;
X len = slashp - source; /* so will be -1 if no suffix */
X if (len > 3)
X len = 3;
X
X for (i = 0; i < len; i++) {
X *dest++ = ToUpper(*source++);
X }
X for (; i < 3; i++) {
X *dest++ = ' ';
X }
X
X return slashp;
X}
X
X/*
X * Do the Info call.
X */
X
Xlong
XMSDiskInfo(infodata)
Xstruct InfoData *infodata;
X{
X extern DEVLIST *VolNode;
X
X setmem(infodata, sizeof (*infodata), 0);
X
X infodata->id_DiskState = IDDiskState;
X infodata->id_DiskType = IDDiskType;
X infodata->id_UnitNumber = UnitNr;
X
X infodata->id_VolumeNode = (BPTR) CTOB(VolNode);
X infodata->id_InUse = LockList ? 1 : 0;
X
X if (IDDiskType == ID_DOS_DISK) {
X infodata->id_NumBlocks = Disk.nsects;
X infodata->id_NumBlocksUsed = Disk.nsects - Disk.nsectsfree;
X infodata->id_BytesPerBlock = Disk.bps;
X }
X return DOSTRUE;
X}
X
X/*
X * We (re-)establish our List of MSFileLocks after a disk has been
X * (re-)inserted. If there are no known locks, we make the root lock from
X * the volume label, if there is one.
X *
X * We get a special cookie to hand to a cleanup routine that we must call
X * when finally all locks on the current disk are UnLock()ed. (this is
X * actually the volume node, but we don't want to know that.)
X *
X * This must be called some time after IdentifyDisk().
X */
X
Xvoid
XMSDiskInserted(locks, cookie)
Xregister struct LockList **locks;
Xvoid *cookie;
X{
X debug(("MSDiskInserted %08lx\n", cookie));
X
X LockList = *locks;
X
X if (LockList == NULL) {
X LockList = NewLockList(cookie);
X RootLock = MakeLock(NULL, &Disk.vollabel, SHARED_LOCK);
X } else {
X RootLock = MSDupLock(GetTail(&LockList->ll_List));
X }
X
X InitCacheList();
X}
X
X/*
X * Remove the current disk. A place is offered to save the current
X * LockList to restore later. We must unlock the root lock since it isn't
X * a real reference to the disk, just a placeholder for dummies that hand
X * us NULL locks.
X */
X
Xint
XMSDiskRemoved(locks)
Xregister struct LockList **locks;
X{
X#ifndef READONLY
X if (FatDirty || (DelayState & DELAY_DIRTY))
X MSUpdate(1); /* Force a requester */
X#endif
X
X FreeFat();
X FreeCacheList();
X
X IDDiskType = ID_NO_DISK_PRESENT;
X *locks = NULL;
X
X if (RootLock == NULL) {
X debug(("MSDiskRemoved with no RootLock\n"));
X return 1;
X }
X#ifdef DEBUG
X if (RootLock != GetTail(&LockList->ll_List)) {
X debug(("RootLock not at end of LockList!\n"));
X /* Get the lock on the root dir at the tail of the List */
X Remove(RootLock);
X AddTail(&LockList->ll_List, RootLock);
X }
X#endif
X
X /*
X * If there are no real locks on the disk, we need not keep any
X * information about it.
X */
X
X MSUnLock(RootLock); /* may call FreeLockList and free VolNode
X * (!) */
X RootLock = NULL;
X
X if (LockList) {
X *locks = LockList; /* VolNode can't be gone now... */
X LockList = NULL;
X return 0; /* not all references gone */
X } else {
X return 1; /* all gone, even the VolNode */
X }
X}
X
Xvoid
XHanCloseDown()
X{
X#ifdef DEBUG
X register struct MSFileLock *fl;
X
X while (LockList && (fl = (struct MSFileLock *) GetHead(&LockList->ll_List))) {
X debug(("UNLOCKING %08lx: ", fl));
X PrintDirEntry(&fl->msfl_Msd);
X MSUnLock(fl); /* Remove()s it from this List */
X }
X#endif
X if (DiskIOReq) {
X if (DiskIOReq->iotd_Req.io_Unit) {
X MSUpdate(1);
X CloseDevice(DiskIOReq);
X }
X DeleteExtIO(DiskIOReq);
X DiskIOReq = NULL;
X }
X if (TimeIOReq) {
X if (TimeIOReq->tr_node.io_Unit) {
X WaitIO(TimeIOReq);
X CloseDevice(TimeIOReq);
X }
X DeleteExtIO(TimeIOReq);
X TimeIOReq = NULL;
X }
X if (DiskReplyPort) {
X DeletePort(DiskReplyPort);
X DiskReplyPort = NULL;
X }
X if (IntuitionBase) {
X CloseLibrary(IntuitionBase);
X IntuitionBase = NULL;
X }
X}
X
Xint
XHanOpenUp()
X{
X LockList = NULL;
X RootLock = NULL;
X Fat = NULL;
X IDDiskState = ID_WRITE_PROTECTED;
X IDDiskType = ID_NO_DISK_PRESENT;
X DelayState = DELAY_OFF;
X Disk.bps = MS_BPS;
X InitCacheList();
X
X TimeIOReq = NULL;
X
X#ifdef DEBUG
X if (!(DiskReplyPort = CreatePort("MSH:disk.replyport", -1L)))
X goto abort;
X#else
X if (!(DiskReplyPort = CreatePort(NULL, -1L)))
X goto abort;
X#endif
X
X debug(("DiskReplyPort = 0x%08lx\n", DiskReplyPort));
X
X if (!(DiskIOReq = CreateExtIO(DiskReplyPort, (long) sizeof (*DiskIOReq)))) {
X debug(("Failed to CreateExtIO\n"));
X goto abort;
X }
X if (OpenDevice(DevName, UnitNr, DiskIOReq, DevFlags | TDF_ALLOW_NON_3_5)) {
X debug(("Failed to OpenDevice\n"));
X goto abort;
X }
X TimeIOReq = (struct timerequest *) CreateExtIO(DiskReplyPort,
X (long) sizeof (*TimeIOReq));
X
X if (TimeIOReq == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, TimeIOReq, 0L))
X goto abort;
X TimeIOReq->tr_node.io_Flags = IOF_QUICK; /* For the first WaitIO() */
X
X IntuitionBase = OpenLibrary("intuition.library", 0L);
X return DOSTRUE;
X
Xabort:
X HanCloseDown();
X return 0;
X}
X
X/*
X * Relabel the disk. We create new labels if necessary.
X */
X
Xlong
XMSRelabel(newname)
Xbyte *newname;
X{
X#ifdef READONLY
X return DOSFALSE;
X#else
X /*
X * A null or empty string means: remove the label, if any.
X */
X if (!newname || !*newname) {
X if ((int) RootLock->msfl_DirSector >= (int) Disk.rootdir) {
X RootLock->msfl_Msd.msd_Name[0] = DIR_DELETED;
X RootLock->msfl_Msd.msd_Attributes = 0;
X WriteFileLock(RootLock);
X RootLock->msfl_Msd = FakeRootDirEntry.de_Msd;
X RootLock->msfl_DirSector = -1;
X Disk.vollabel = FakeRootDirEntry;
X }
X return DOSTRUE;
X }
X /*
X * No label yet? Then we must create one, even if we need to move
X * something else for it.
X */
X
X if ((int) RootLock->msfl_DirSector < 0) {
X struct MSFileLock *new;
X
X new = MSLock(RootLock, "><>.\\", EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
X if ((new == NULL) && (new = EmptyFileLock)) {
X error = 0;
X if (new->msfl_DirSector == Disk.rootdir) {
X RootLock->msfl_DirSector = Disk.rootdir;
X RootLock->msfl_DirOffset = new->msfl_DirOffset;
X } else {
X /*
X * Move something out of the first directory block. Try
X * not to move system files or directories (. ..), but
X * we'll do it if we need to. Set the root dir date to
X * now.
X */
X byte *fromsec;
X byte *tosec;
X register struct MsDirEntry *dir;
X
X fromsec = GetSec(Disk.rootdir);
X tosec = GetSec(new->msfl_DirSector);
X
X dir = (struct MsDirEntry *) fromsec;
X while (dir->msd_Attributes & (ATTR_SYSTEM | ATTR_DIRECTORY)) {
X if ((byte *) ++dir >= fromsec + Disk.bps) {
X --dir; /* Back to last entry in the block */
X break; /* and move it no matter what */
X }
X }
X CopyMem(dir, tosec + new->msfl_DirOffset,
X (long) sizeof (struct MsDirEntry));
X MarkSecDirty(tosec);
X RootLock->msfl_DirSector = Disk.rootdir;
X RootLock->msfl_DirOffset = (byte *) dir - fromsec;
X
X FreeSec(tosec);
X FreeSec(fromsec);
X
X }
X }
X EmptyFileLock = NULL;
X MSUnLock(new);
X }
X if ((int) RootLock->msfl_DirSector >= Disk.rootdir) {
X struct DateStamp dateStamp;
X
X /*
X * The easy part: Copy the name to Disk.vollabel and RootLock.
X */
X {
X register int i;
X register byte *s,
X *d;
X
X s = newname;
X d = Disk.vollabel.de_Msd.msd_Name;
X for (i = 0; i < 8 + 3; i++) {
X if (s[0])
X *d++ = ToUpper(*s++);
X else
X *d++ = ' ';
X }
X }
X DateStamp(&dateStamp);
X ToMSDate(&Disk.vollabel.de_Msd.msd_Date,
X &Disk.vollabel.de_Msd.msd_Time, &dateStamp);
X RootLock->msfl_Msd = Disk.vollabel.de_Msd; /* Just for the name and
X * date */
X WriteFileLock(RootLock);
X
X return DOSTRUE;
X }
X return DOSFALSE;
X#endif
X}
X
X#ifdef DEBUG
X
X_abort()
X{
X HanCloseDown();
X RemTask(NULL);
X}
X
X#endif /* DEBUG */
END_OF_FILE
if test 10114 -ne `wc -c <'src/hanmain.c'`; then
echo shar: \"'src/hanmain.c'\" unpacked with wrong size!
fi
# end of 'src/hanmain.c'
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 6 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.